#pragma once

template <class K>
class BSTNode 
{
public:
	BSTNode<K>* left;
	BSTNode<K>* right;
	K key;

	BSTNode(const K& key)
		:left(nullptr)
		,right(nullptr)
		,key(key)
	{}
};

template <class K>
class BST
{
public:
	typedef BSTNode<K> Node;
	BST()
		:_root(nullptr)
	{
	}

	BST(const BST<K>& t)
	{
		_root = copy(t.root);
	}

	~BST()
	{
		Destroy(_root);
	}

	BST<K>& operator=(BST<K> t)
	{
		swap(_root, t._root);
		return *this;
	}


	Node* copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* copynode = new Node(root->key);
		copynode->left = copy(root->left);
		copynode->right = copy(root->right);
		return copynode;
	}

	void Destroy(Node*& root)
	{
		//后序遍历方便删除
		if (root == nullptr)
		{
			return;
		}

		Destroy(root->left);
		Destroy(root->right);
		delete root;
		root = nullptr;
	}

	bool call_RInsert(const K& key)
	{
		return RInsert(_root, key);
	}

	bool RInsert(Node*& root, const K& key)
	{
		//用传引用的方式解决链接问题
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}

		if (root->key < key)
		{
			return RFind(root->right, key);
		}
		else if (root->key > key)
		{
			return RFind(root->left, key);
		}
		else
		{
			return false;
		}
	}

	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->key < key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->key > key)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(key);
		if (parent->key < key)
		{
			parent->right = cur;
		}
		else
		{
			parent->left = cur;
		}
		return true;   
	}

	bool call_RFind(const K& key)
	{
		return RFind(_root, key);
	}

	bool RFind(Node* root, const K& key)
	{
		if (root == nullptr)
			return false;

		if (root->key < key)
		{
			return RFind(root->right, key);
		}
		else if (root->key > key)
		{
			return RFind(root->left, key);
		}
		else
		{
			return true;
		}
	}

	void Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->key < key)
			{
				cur = cur->right;
			}
			else if (cur->key > key)
			{
				cur = cur->left;
			}
			else
			{
				return true;
			}
		}

		return false;
	}

	bool call_RErase(const K& key)
	{
		return RErase(_root, key);
	}

	bool RErase(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}


		if (root->key < key)
		{
			return RErase(root->right, key);
		}
		else if (root->key > key)
		{
			return RErase(root->left, key);
		}
		else
		{
			Node* del = root;
			if (root->left == nullptr)
			{
				root = root->right;
			}
			else if (root->right == nullptr)
			{
				root = root->left;
			}
			else
			{
				Node* leftmax = root->left;
				while (leftmax->right)
				{
					leftmax = leftmax->right;
				}

				swap(root->key, leftmax->key);
				//替换在左子树中删除原值
				return RErase(root->left, key);
			}
			delete del;
			return true;
		}
	}

	bool Erase(const K& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;

		while (cur)
		{
			if (cur->key < key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->key > key)
			{
				parent = cur;
				cur = cur->left;
			}
			else 
			{
				if (cur->left == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->right;
					}
					else
					{
						if (parent->right == cur)
						{
							parent->right = cur->right;
						}
						else
						{
							parent->left = cur->right;
						}
					}
				}
				else if (cur->right == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->left;
					}
					else
					{
						if (parent->left == cur)
						{
							parent->left = cur->left;
						}
						else
						{
							parent->right = cur->left;
						}
					}
				}
				else
				{
					Node* leftmax = cur->left;
					parent = cur;

					while (leftmax->right)
					{
						parent = leftmax;
						leftmax = leftmax->right;
					}
					swap(cur->key, leftmax->key);

					if (parent->left == leftmax)
					{
						//右子树为空之后将左子树给根
						parent->left = leftmax->left;
					}
					else
					{
						parent->right = leftmax->left;
					}

					cur = leftmax;
				}

				delete cur;
				return true;
			}
		}

		return false;
	}

	void call_InOrder()
	{
		InOrder(_root);
		cout << endl;
	}

	void InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		InOrder(root->left);
		cout << root->key <<" ";
		InOrder(root->right);
	}
	

private:
	Node* _root;
};


void TestBSTree1()
{
	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
	BST<int> t;
	for (auto e : a)
	{
		t.Insert(e);
	}

	t.call_InOrder();
}